import {computed, designComponent, nextTick, onBeforeUnmount, PropType, reactive, useRefs, watch} from "plain-design-composition";
import {BackListener, MicroUtils, Page, Tab} from "plain-micro-application";
import {MicroNavigatorTabProvider} from "@/micro/nav/utils/micro.navigator.tab.provider";
import {nav} from "@/micro/nav/nav";
import {NavigatorEventHandler} from "../utils/micro.navigator.event";
import {PlLoadingMask} from "plain-design";
import React from "react";
import {useMicroNavigatorPageSingleCase} from "@/micro/nav/components/useMicroNavigatorPageSingleCase";
import {createPageLoading} from "@/micro/nav/utils/createLoading.micro";

export const MicroNavigatorPage = designComponent({
    props: {
        page: {type: Object as PropType<Page>, required: true},
        tab: {type: Object as PropType<Tab>, required: true},
        show: {type: Boolean},
    },
    setup({props}) {

        const state = reactive({
            // 当前是否加载子应用失败
            loadMicroAppError: false,
        })
        const entryPublicPath = MicroUtils.EntryApplicationPublicPathConfigure.get()
        const {refs, onRef} = useRefs({el: HTMLDivElement})
        const tab = MicroNavigatorTabProvider.inject()
        const loading = createPageLoading();
        const {singleCaseState, onPageInit} = useMicroNavigatorPageSingleCase({loading})

        let unmountHandler: null | (() => void) = null;
        let unwatchBackWatcher: null | (() => void) = null;

        const backHandler = (() => {
            const listeners: BackListener[] = []
            return {
                emit: (backData: any) => listeners.forEach(i => i(backData)),
                on: (fn: BackListener) => listeners.push(fn),
            }
        })();

        watch(() => props.page.init, async init => {
            if (init) {
                loading.start();
                try {
                    const microInfo = await nav.micro.getLoader(props.page)
                    if (!microInfo) {
                        return state.loadMicroAppError = true
                    }
                    const {loader, app} = microInfo
                    await nextTick();

                    if (!app.config.singleCase) {
                        /*非单例模式*/
                        unmountHandler = await loader({
                            el: refs.el!,
                            page: props.page,
                            tab,
                            nav: nav.createService(props.page, tab),
                            onBack: backHandler.on,
                            entryPublicPath,
                        })
                        if (!!unwatchBackWatcher) {unwatchBackWatcher()}
                        unwatchBackWatcher = watch(() => props.page.backWatcher, () => {backHandler.emit(props.page.backData)})
                    } else {
                        /*单例模式，只要是这个子应用的页面，只用一个div显示*/
                        onPageInit({app, props, entryPublicPath})
                    }
                } catch (e) {
                    console.error(e)
                    return state.loadMicroAppError = true
                } finally {
                    loading.done()
                }
            }
        }, {immediate: true});

        const wrapperElAttrs = computed(() => {
            const attrs = {} as any
            attrs['data-tab-id'] = props.tab.id
            attrs['data-page-path'] = props.page.path
            attrs.style = {}
            attrs.style.display = props.show ? '' : 'none'

            if (singleCaseState.isAppSingle) {
                attrs.style.display = 'none'
                attrs['data-single-app'] = "source"
            }
            return attrs
        })

        onBeforeUnmount(() => {
            !!unmountHandler && unmountHandler()
            !!unwatchBackWatcher && unwatchBackWatcher()
            NavigatorEventHandler.onBeforeUnmount.page(props.page)
        })

        return () => <>
            <div
                className="micro-navigator-page"
                ref={onRef.el}
                {...wrapperElAttrs.value}
            >
                {state.loadMicroAppError && (
                    <div>
                        子应用加载失败：{props.page.path}
                    </div>
                )}
                {singleCaseState.isAppSingle && <span>单例子应用，这里不渲染内容</span>}
            </div>
            <PlLoadingMask modelValue={props.show && loading.loading || props.page.loading} message={loading.loadingMessage} loadingType="alpha"/>
        </>
    },
})
